vmx: Fix handling of FS/GS base MSRs.
authorKeir Fraser <keir.fraser@citrix.com>
Thu, 16 Jul 2009 09:26:55 +0000 (10:26 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Thu, 16 Jul 2009 09:26:55 +0000 (10:26 +0100)
Firstly, these MSRs are always accessible if the CPU supports them --
we should not check for EFER.LMA.

Secondly, we should not use teh cached value of shadow_gs while the
VCPU is running. It can be stale if the guest has executed SWAPGS
(which we cannot trap). Hence always access the underlying host MSR
when emulating guest accesses.

The latter bug was found and a patch proposed by <leonid@3tera.com>

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
xen/arch/x86/hvm/vmx/vmx.c

index e568a2b563f0c64e3d1ea8e0defe619aa384ef56..df8cccba525077d81abc9b84df6042b812513485 100644 (file)
@@ -177,20 +177,14 @@ static enum handler_return long_mode_do_msr_read(struct cpu_user_regs *regs)
 
     case MSR_FS_BASE:
         msr_content = __vmread(GUEST_FS_BASE);
-        goto check_long_mode;
+        break;
 
     case MSR_GS_BASE:
         msr_content = __vmread(GUEST_GS_BASE);
-        goto check_long_mode;
+        break;
 
     case MSR_SHADOW_GS_BASE:
-        msr_content = v->arch.hvm_vmx.shadow_gs;
-    check_long_mode:
-        if ( !(hvm_long_mode_enabled(v)) )
-        {
-            vmx_inject_hw_exception(TRAP_gp_fault, 0);
-            return HNDL_exception_raised;
-        }
+        rdmsrl(MSR_SHADOW_GS_BASE, msr_content);
         break;
 
     case MSR_STAR:
@@ -241,9 +235,6 @@ static enum handler_return long_mode_do_msr_write(struct cpu_user_regs *regs)
     case MSR_FS_BASE:
     case MSR_GS_BASE:
     case MSR_SHADOW_GS_BASE:
-        if ( !hvm_long_mode_enabled(v) )
-            goto gp_fault;
-
         if ( !is_canonical_address(msr_content) )
             goto uncanonical_address;
 
@@ -252,10 +243,7 @@ static enum handler_return long_mode_do_msr_write(struct cpu_user_regs *regs)
         else if ( ecx == MSR_GS_BASE )
             __vmwrite(GUEST_GS_BASE, msr_content);
         else
-        {
-            v->arch.hvm_vmx.shadow_gs = msr_content;
             wrmsrl(MSR_SHADOW_GS_BASE, msr_content);
-        }
 
         break;
 
@@ -284,7 +272,6 @@ static enum handler_return long_mode_do_msr_write(struct cpu_user_regs *regs)
 
  uncanonical_address:
     HVM_DBG_LOG(DBG_LEVEL_0, "Not cano address of msr write %x", ecx);
- gp_fault:
     vmx_inject_hw_exception(TRAP_gp_fault, 0);
  exception_raised:
     return HNDL_exception_raised;
@@ -311,7 +298,10 @@ static void vmx_restore_host_msrs(void)
 
 static void vmx_save_guest_msrs(struct vcpu *v)
 {
-    /* MSR_SHADOW_GS_BASE may have been changed by swapgs instruction. */
+    /*
+     * We cannot cache SHADOW_GS_BASE while the VCPU runs, as it can
+     * be updated at any time via SWAPGS, which we cannot trap.
+     */
     rdmsrl(MSR_SHADOW_GS_BASE, v->arch.hvm_vmx.shadow_gs);
 }